package lc.com.lcpicturebackend.service.impl;


import cn.hutool.core.util.ObjUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lc.com.lcpicturebackend.exception.BusinessException;
import lc.com.lcpicturebackend.exception.ErrorCode;
import lc.com.lcpicturebackend.exception.ThrowUtils;
import lc.com.lcpicturebackend.mapper.SpaceMapper;
import lc.com.lcpicturebackend.model.dto.space.analyze.*;
import lc.com.lcpicturebackend.model.entity.Picture;
import lc.com.lcpicturebackend.model.entity.Space;
import lc.com.lcpicturebackend.model.entity.User;
import lc.com.lcpicturebackend.model.vo.analyze.*;
import lc.com.lcpicturebackend.service.PictureService;
import lc.com.lcpicturebackend.service.SpaceAnalyzeService;
import lc.com.lcpicturebackend.service.SpaceService;
import lc.com.lcpicturebackend.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 功能：
 * 作者：lc
 * 日期：2025/3/4 21:12
 */
@Slf4j
@Service
public class SpaceAnalyzeServiceImpl extends ServiceImpl<SpaceMapper, Space>
        implements SpaceAnalyzeService {
    @Resource
    private UserService userService;
    @Resource
    private SpaceService spaceService;
    @Resource
    private PictureService pictureService;

    @Override
    public SpaceUsageAnalyzeResponse getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest usageAnalyzeRequest, User loginUser) {
        // 校验参数
        ThrowUtils.throwIf(usageAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 检查用户空间分析权限
        checkSpaceAnalyzeAuth(usageAnalyzeRequest, loginUser);

        if (usageAnalyzeRequest.isQueryAll() || usageAnalyzeRequest.isQueryPublic()) {
            // 修改空间查询范围
            // 1.仅管理员的全查询
            checkSpaceAnalyzeAuth(usageAnalyzeRequest, loginUser);
            // 统计公共图库的资源使用
            QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
            // 因为查询全图的使用的资源不好在space中查找，只能在picture中查找出来后相加计算的到结果
            queryWrapper.select("picSize");
            fillAnalyzeQueryWrapper(usageAnalyzeRequest, queryWrapper);
            // 从数据库中查询这里不要使用this.list(),因为list()、selectList()返回的对象集合，可以使用getBaseMapper中的selectObject,selectCount,selectMap,selectOne
            List<Object> objectList = pictureService.getBaseMapper().selectObjs(queryWrapper);
            // 封装返回对象
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            // 计算公共图库的总的资源使用情况
            spaceUsageAnalyzeResponse.setUsedSize(objectList.stream().mapToLong(obj -> (Long) obj).sum());
            // 公共空间没有使用总量
            spaceUsageAnalyzeResponse.setMaxSize(null);
            spaceUsageAnalyzeResponse.setSizeUsageRatio(null);
            spaceUsageAnalyzeResponse.setUsedCount((long) objectList.size());
            spaceUsageAnalyzeResponse.setMaxCount(null);
            spaceUsageAnalyzeResponse.setCountUsageRatio(null);
            return spaceUsageAnalyzeResponse;
        } else {
            // 2.普通用户查询自己的空间分析
            Long spaceId = usageAnalyzeRequest.getSpaceId();
            if (spaceId == null || spaceId <= 0) {
                throw new BusinessException(ErrorCode.PARAMS_ERROR);
            }
            Space space = spaceService.getById(spaceId);
            if (space == null) {
                throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
            }
            // 封装返回对象
            SpaceUsageAnalyzeResponse spaceUsageAnalyzeResponse = new SpaceUsageAnalyzeResponse();
            spaceUsageAnalyzeResponse.setUsedSize(space.getTotalSize());
            spaceUsageAnalyzeResponse.setMaxSize(space.getMaxSize());
            // 计算空间图片使用比例
            Double usageSizeRatio = space.getTotalSize() * 1.0 / space.getMaxSize();
            spaceUsageAnalyzeResponse.setSizeUsageRatio(usageSizeRatio);
            spaceUsageAnalyzeResponse.setUsedCount(space.getTotalCount());
            spaceUsageAnalyzeResponse.setMaxCount(space.getMaxCount());
            // 计算空间图片数量使用比例
            double usageCountRatio = space.getTotalCount() * 1.0 / space.getMaxCount();
            spaceUsageAnalyzeResponse.setCountUsageRatio(usageCountRatio);
            return spaceUsageAnalyzeResponse;
        }
    }

    @Override
    public List<SpaceCategoryAnalyzeResponse> getSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest categoryAnalyzeRequest,
                                                                      User loginUser) {
        ThrowUtils.throwIf(categoryAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 1.校验权限
        checkSpaceAnalyzeAuth(categoryAnalyzeRequest, loginUser);

        // 2.查询分类
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(categoryAnalyzeRequest, queryWrapper);
        // 分组查询
        queryWrapper.select("category", "count(*) AS count", "sum(picSize) AS totalSize")
                .groupBy("category");
        // 查询并返回结果
        return pictureService.getBaseMapper().selectMaps(queryWrapper).stream().map(result -> {
            // String category = (String) result.get("category");
            // Long count = (Long) result.get("count");
            // Long totalSize = (Long) result.get("totalSize");
            String category = result.get("category") != null ? result.get("category").toString() : "未分类";
            Long count = ((Number) result.get("count")).longValue();
            Long totalSize = ((Number) result.get("totalSize")).longValue();
            return new SpaceCategoryAnalyzeResponse(category, count, totalSize);
        }).collect(Collectors.toList());
    }

    @Override
    public List<SpaceTagAnalyzeResponse> getSpaceResourceTagAnalyze(SpaceTagAnalyzeRequest tagAnalyzeRequest,
                                                                    User loginUser) {
        ThrowUtils.throwIf(tagAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 1.校验权限
        checkSpaceAnalyzeAuth(tagAnalyzeRequest, loginUser);

        // 2.查询分类
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(tagAnalyzeRequest, queryWrapper);
        queryWrapper.select("tags");
        List<String> tagsJsonList = pictureService.getBaseMapper()
                .selectObjs(queryWrapper)
                .stream()
                .filter(ObjUtil::isNotEmpty)
                .map(Object::toString)
                .collect(Collectors.toList());
        // 3.统计标签,进行扁平化处理后，统计
        // ["JAVA", "PYTHON"]=>"JAVA", "PYTHON"
        Map<String, Long> tagCountMap = tagsJsonList.stream()
                .flatMap(tagsJson -> JSONUtil.toList(tagsJson, String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        // 转换为响应类，并通过使用次数排序
        return tagCountMap.entrySet().stream()
                .sorted((e1, e2) -> Long.compare(e2.getValue(), e1.getValue()))
                .map(entry -> new SpaceTagAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpaceSizeAnalyzeResponse> getSpaceResourceSizeAnalyze(
            SpaceSizeAnalyzeRequest sizeAnalyzeRequest,
            User loginUser) {
        ThrowUtils.throwIf(sizeAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 1.校验权限
        checkSpaceAnalyzeAuth(sizeAnalyzeRequest, loginUser);

        // 2.查询分类
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(sizeAnalyzeRequest, queryWrapper);
        queryWrapper.select("picSize");
        // 3.查询图片数据
        List<Long> sizeJsonList = pictureService.getBaseMapper()
                .selectObjs(queryWrapper).stream()
                .map(sizeJson -> ((Number) sizeJson).longValue())
                .collect(Collectors.toList());
        // 4.定义分段范围，
        LinkedHashMap<String, Long> sizeRangeMap = new LinkedHashMap<>();
        sizeRangeMap.put("<50KB", sizeJsonList.stream().filter(size -> size < 50 * 1024).count());
        sizeRangeMap.put("50KB-500KB", sizeJsonList.stream().filter(size -> size >= 50 * 1024 && size < 500 * 1024).count());
        sizeRangeMap.put("500KB-2MB", sizeJsonList.stream().filter(size -> size >= 500 * 1024 && size < 2 * 1024 * 1024).count());
        sizeRangeMap.put(">2MB", sizeJsonList.stream().filter(size -> size >= 2 * 1024 * 1024).count());
        // 5.返回结果
        return sizeRangeMap.entrySet().stream()
                .map(entry -> new SpaceSizeAnalyzeResponse(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());

    }

    @Override
    public List<SpaceUserAnalyzeResponse> getSpaceUserAnalyze(SpaceUserAnalyzeRequest userAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(userAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);
        // 1.校验权限
        checkSpaceAnalyzeAuth(userAnalyzeRequest, loginUser);

        // 2.查询分类
        Long userId = userAnalyzeRequest.getUserId();
        String timeDimension = userAnalyzeRequest.getTimeDimension();
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        fillAnalyzeQueryWrapper(userAnalyzeRequest, queryWrapper);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId), "userId", userId);
        switch (timeDimension) {
            case "day":
                queryWrapper.select("DATE_FORMAT(createTime,'%Y-%m-%d') as date", "count(*) as count").groupBy("date");
                break;
            case "week":
                queryWrapper.select("DATE_FORMAT(createTime,'%Y-%u') as date", "count(*) as count").groupBy("date");
                break;
            case "month":
                queryWrapper.select("DATE_FORMAT(createTime,'%Y-%m') as date", "count(*) as count").groupBy("date");
                break;
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "查询时间维度错误");
        }
        queryWrapper.groupBy("date").orderByAsc("date");
        // 3.查询
        List<Map<String, Object>> queryResult = pictureService.getBaseMapper().selectMaps(queryWrapper);
        return queryResult.stream()
                .map(res -> {
                    String date = res.get("date").toString();
                    Long count = ((Number) res.get("count")).longValue();
                    return new SpaceUserAnalyzeResponse(date, count);
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<Space> getSpaceRankAnalyze(SpaceRankAnalyzeRequest spaceRankAnalyzeRequest, User loginUser) {
        ThrowUtils.throwIf(spaceRankAnalyzeRequest == null, ErrorCode.PARAMS_ERROR);

        // 仅管理员可查看空间排行
        ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR, "无权查看空间排行");

        // 构造查询条件
        QueryWrapper<Space> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("id", "spaceName", "userId", "totalSize")
                .orderByDesc("totalSize")
                .last("LIMIT " + spaceRankAnalyzeRequest.getTopN()); // 取前 N 名

        // 查询结果
        return spaceService.list(queryWrapper);
    }

    /**
     * 检查用户空间空间分析权限
     *
     * @param spaceAnalyzeRequest 空间id
     * @param loginUser           登录用户
     */
    private void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest spaceAnalyzeRequest, User loginUser) {
        boolean queryAll = spaceAnalyzeRequest.isQueryAll();
        boolean queryPublic = spaceAnalyzeRequest.isQueryPublic();
        // 1.管理员才能查到所有和公共图库
        if (queryAll || queryPublic) {
            ThrowUtils.throwIf(!userService.isAdmin(loginUser), ErrorCode.NO_AUTH_ERROR);
        } else {
            // 2.查询自己的图库
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            ThrowUtils.throwIf(ObjUtil.isEmpty(spaceId), ErrorCode.PARAMS_ERROR);
            Space space = this.getById(spaceId);
            ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "图库不存在");
            spaceService.checkSpaceAuth(space, loginUser);
        }
    }

    /**
     * 分析范围填充查询对象
     *
     * @param spaceAnalyzeRequest 空间分析请求
     * @param queryWrapper        查询对象
     */
    private void fillAnalyzeQueryWrapper(SpaceAnalyzeRequest spaceAnalyzeRequest, QueryWrapper<Picture> queryWrapper) {
        {
            if (spaceAnalyzeRequest.isQueryAll()) {
                return;
            }
            if (spaceAnalyzeRequest.isQueryPublic()) {
                queryWrapper.isNull("spaceId");
                return;
            }
            Long spaceId = spaceAnalyzeRequest.getSpaceId();
            if (spaceId != null) {
                queryWrapper.eq("spaceId", spaceId);
                return;
            }
        }
        throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "未查询到合适数据");
    }


}
